package mobile.TheOldRepublic.util;

import java.io.File;
import java.io.IOException;
import java.util.concurrent.LinkedBlockingQueue;

import android.content.Context;
import android.util.Log;

abstract public class Downloader extends Thread {
	
	public static String FILE_ROOT = "";
	
	protected static Downloader activeThread = null;
	protected LinkedBlockingQueue<BgDownloadFile> downloadQueue = new LinkedBlockingQueue<BgDownloadFile>();
	protected BgDownloadFile currentDownload = null;
		
	public static Downloader getInstance()
	{
		throw new IllegalStateException("getInstance must be defined in subclass");
	}
	
	public BgDownloadFile getCurrentDownload(){
		return currentDownload;
	}
	
	/*@Override
	public void start(){
		if(!isAlive()){
			Log.d(getClass().getSimpleName(), "Starting Downloader");
			super.start();
		}
	}*/
	
	/**
	 * Queue a file to be downloaded.  If the file has already been downloaded then that file will be used.
	 * @param url The URL to download the file from.
	 * @param outputDir The directory to save the file to.
	 * @return The name of the file after it's been downloaded.
	 */
	public String addFileToDownload(String url, File outputDir){
		File outFile = new File(outputDir, parseFilename(url));
		if(!outFile.exists()){
			BgDownloadFile iofn = new BgDownloadFile();
			iofn.inputUrl = url;
			iofn.outputDirectory = outputDir;
			iofn.outputFilename = outFile.getName();
			downloadQueue.offer(iofn);
		}
		return outFile.getName();
	}
	
	/**
	 * Force a file to be downloaded regardless of if it already has been.
	 * @param url The URL to download the file from.
	 * @param outputDir The directory to save the file to.
	 * @return The name of the file after it's been downloaded.
	 */
	public String forceFileToDownload(String url, File outputDir){
		BgDownloadFile iofn = new BgDownloadFile();
		iofn.inputUrl = url;
		iofn.outputDirectory = outputDir;
		iofn.outputFilename = parseFilename(url);
		iofn.forceDownload = true;
		downloadQueue.offer(iofn);
		
		return iofn.outputFilename;
	}
	
	/**
	 * Take a URL and parse the file name to store it as.
	 * @param name The URL to parse.
	 * @return The name to use for the file once downloaded.
	 */
	public static String parseFilename(String name){
		if(name.contains("/")){
			String[] split = name.split("\\/");
			name = split[split.length-1];
		}
		name = name.split("\\.")[0]+FILE_ROOT;
		return name;
	}
	
	@Override
	public void run(){
		if(currentDownload == null)
			this.downloadFiles();
	}
	
	private synchronized void downloadFiles()
	{
		Log.d(this.getClass().getSimpleName(), "Start downloadFiles");
		if(currentDownload != null){
			Log.d(getClass().getSimpleName(), "waiting, currentDownload = "+currentDownload.inputUrl);
			try{ wait(); }catch(InterruptedException ie){}
		}
		Log.d(this.getClass().getSimpleName(), "wait complete");
		BgDownloadFile file;
		while((file = downloadQueue.poll()) != null){
			try{
				Log.d(this.getClass().getSimpleName(), "downloading loop "+file.inputUrl);
				currentDownload = file;
				downloadFile(file, null, true);
			}catch(IOException ioe){}
			currentDownload = null;
			Log.d(this.getClass().getSimpleName(), "yielding control");
			yield();
		}
		Log.d(this.getClass().getSimpleName(), "End downloadFiles");
		activeThread = null;
	}
		
	abstract protected void downloadFile(BgDownloadFile file, Context context, boolean externalOnly) throws IOException;

	public static class BgDownloadFile{
		public String inputUrl = null;
		public long inputSize = -1;
		public File outputDirectory = null;
		public String outputFilename = null;
		public boolean forceDownload = false;
	}
}
